#include "qb_base_impl.h"

#include <core/QbLogger.h>
#include <core/sharedata/login_data.h>

#include "qbmessage/include/message_bond.h"
#include "qbmessage/include/message_kernel.h"
#include "qbmessage/include/message_process.h"
#include "qbmessage/include/message_sync.h"

namespace qb {
static qbBaseImpl* s = nullptr;
static scoped_refptr<INetworkService> m_spNetworkService = NULL;  // 网络
static scoped_refptr<IMessageKernel> m_spMessageKernel = NULL;  // 消息中心
static scoped_refptr<IMessageProcess> m_spMessageProcess =
    NULL;  // 消息处理模块
static scoped_refptr<IMessageSync> m_spMessageSync = NULL;  // 消息同步模块
static scoped_refptr<IMessageBond> m_spMessageBond = NULL;  // 债券

qbBase* qbBase::getInterface() {
  if (s == nullptr) {
    s = new qbBaseImpl();
  }

  return s;
}

scoped_refptr<IMessageKernel> qbBase::getMessageKernel() {
  QB_CHECK_RETURN_VALUE_ASSERT(s, NULL);

  if (!m_spMessageKernel) {
    if (0 != s->QueryInterface(CLSID_MessageKernel, IID_IMessageKernel,
                               (void**)&m_spMessageKernel)) {
      return NULL;
    }
  }

  return m_spMessageKernel;
}

scoped_refptr<IMessageProcess> qbBase::getMessageProcess() {
  QB_CHECK_RETURN_VALUE_ASSERT(s, NULL);

  if (!m_spMessageProcess) {
    if (0 != s->QueryInterface(CLSID_MessageKernel, IID_IMessageProcess,
                               (void**)&m_spMessageProcess)) {
      return NULL;
    }
  }

  return m_spMessageProcess;
}

scoped_refptr<IMessageBond> qbBase::getMessageBond() {
  QB_CHECK_RETURN_VALUE_ASSERT(s, NULL);

  if (!m_spMessageBond) {
    if (0 != s->QueryInterface(CLSID_MessageKernel, IID_IMessageBond,
                               (void**)&m_spMessageBond)) {
      return NULL;
    }
  }

  return m_spMessageBond;
}

scoped_refptr<IMessageSync> qbBase::getMessageSync() {
  QB_CHECK_RETURN_VALUE_ASSERT(s, NULL);

  if (!m_spMessageSync) {
    if (0 != s->QueryInterface(CLSID_MessageKernel, IID_IMessageSync,
                               (void**)&m_spMessageSync)) {
      return NULL;
    }
  }

  return m_spMessageSync;
}

scoped_refptr<INetworkService> qbBase::getNetworkService() {
  QB_CHECK_RETURN_VALUE_ASSERT(s, NULL);

  if (!m_spNetworkService) {
    if (0 != s->QueryInterface(CLSID_NetworkService, IID_INetworkService,
                               (void**)&m_spNetworkService)) {
      return NULL;
    }
  }

  return m_spNetworkService;
}

qbBaseImpl::qbBaseImpl() {}

qbBaseImpl::~qbBaseImpl() { DestroyQbModule(); }

int32_t qbBaseImpl::init(const char* exepath) {
  if (m_modules.LoadResource(exepath) == -1) {
    log_error("load resource failed");
    return -1;
  }

  CreateQbModule();
  return 0;
}

int32_t qbBaseImpl::terminate() {
  DestroyQbModule();
  m_terminated = true;
  if (m_modules.UnloadResource() == -1) {
    log_warning("unload resource failed");
    return -1;
  }

  return 0;
}

int32_t qbBaseImpl::QueryInterface(REFCLSID rclsid, REFIID riid, void** ppv) {
  if (m_terminated) return 0;
  return m_modules.QueryInterface(rclsid, riid, ppv);
}

void qbBaseImpl::CreateQbModule() {
  InitModule_NetworkService();
  InitModule_MessageProcessor();
}

void qbBaseImpl::InitModule_NetworkService() {
  if (!m_spNetworkService) {
    if (0 != QueryInterface(CLSID_NetworkService, IID_INetworkService,
                            (void**)&m_spNetworkService)) {
      return;
    }
  }
}

void qbBaseImpl::InitModule_MessageProcessor() {
  if (!m_spMessageSync) {
    if (0 != QueryInterface(CLSID_MessageKernel, IID_IMessageSync,
                            (void**)&m_spMessageSync)) {
      return;
    }
    if (!m_spMessageSync || !m_spMessageSync->Create()) return;
  }

  if (!m_spMessageProcess) {
    if (0 != QueryInterface(CLSID_MessageKernel, IID_IMessageProcess,
                            (void**)&m_spMessageProcess)) {
      return;
    }
    if (!m_spMessageProcess) {
      return;
    }
    if (0 != m_spMessageProcess->Create(m_spNetworkService, m_spMessageSync)) {
      return;
    }
  }

  if (!m_spMessageKernel) {
    if (-1 == QueryInterface(CLSID_MessageKernel, IID_IMessageKernel,
                             (void**)&m_spMessageKernel)) {
      return;
    }
    if (!m_spMessageKernel) {
      return;
    }
    if (0 != m_spMessageKernel->Create(m_spNetworkService, m_spMessageSync,
                                       m_spMessageProcess)) {
      return;
    }
  }

  if (!m_spMessageBond) {
    if (0 != QueryInterface(CLSID_MessageKernel, IID_IMessageBond,
                            (void**)&m_spMessageBond)) {
      return;
    }
    if (!m_spMessageBond) {
      return;
    }
    if (0 != m_spMessageBond->Create(m_spNetworkService, m_spMessageKernel,
                                     m_spMessageProcess)) {
      return;
    }
  }
}

void qbBaseImpl::UnInitModule_NetworkService() { m_spNetworkService = NULL; }

void qbBaseImpl::UnInitModule_MessageProcessor() {
  if (m_spMessageBond) {
    m_spMessageBond->Destory();
    m_spMessageBond = NULL;
  }
  if (m_spMessageKernel) {
    m_spMessageKernel->Destory();
    m_spMessageKernel = NULL;
  }
  if (m_spMessageProcess) {
    m_spMessageProcess->Destory();
    m_spMessageProcess = NULL;
  }

  m_spMessageSync = NULL;
}

void qbBaseImpl::DestroyQbModule() {
  UnInitModule_MessageProcessor();
  UnInitModule_NetworkService();
}

scoped_refptr<INetworkService> qbBaseImpl::getNetworkService() {
  if (!m_spNetworkService) {
    if (0 != QueryInterface(CLSID_NetworkService, IID_INetworkService,
                            (void**)&m_spNetworkService)) {
      return NULL;
    }
  }

  return m_spNetworkService;
}
}  // namespace qb
